
TUTORIAL NOTES ON RELOCATABLE CODE

     To relocate any code, one identifies the source (where the code is
coming from), the destination (where it's going), and the size (how much
code to move).	The common program sequence is:
	LD	HL,SOURCE
	LD	DE,DEST
	LD	BC,SIZE
	LDIR
The difficulty arises in that the program in low memory being moved to
high memory will have all its addresses defined by its low memory location.
Programmers have used several successful techniques to compensate for this.
The technique I've gotten accustomed to is the use of offsets.	An offset
is provided for every address that is referenced ABSOLUTE but is not
provided for any address referenced RELATIVE.  All  JP	and  CALL  commands
require an absolute address.  All  JR  and  DJNZ  commands require a relative
address.  A specific address may occasionally require both.  Consider as
an example the code below:

OU	EQU	DEST-SOURCE	; offset
CONIN	EQU	$+OU		; conin - relocated address  (absolute)
CONINL: 			; conin - local address      (relative)
	CALL	CONST		; call console status check
	JR	Z,CONINL	; loop until status says we're ready
	CALL	0F600H		; get the byte using upper bios
	CP	9BH		; see if it's CMND-F1
	JR	NZ,CN9C 	;    (continuous pop-up clk display)
	LD	A,(CLKFLG)	; prepare to toggle the pop-up flag
	CPL			; complement the accumulator
	LD	(CLKFLG),A	; store the toggled flag
	JR	CONINL		; go back for next input
CN9C:	CP	7FH		; see if it's a "delete"
	RET	NZ		; if not, return with it the input byte
	LD	A,08h		; if yes, transform it into ^H
	RET			; done with CONIN
CLKFLG	EQU	$+OU
	DB	0		; flag to see if clock display requested

In this example, CONIN is the absolute address and CONINL is the same
location but in relative terms.  The relative address is needed to
support the  JR Z,CONINL  command.  The absolute address is needed to
support the  JP CONIN  in the bios jump table.	 Similarly,  CLKFLG
is an absolute address because it's the object of a  LD  A,(CLKFLG)
instruction, while CN9C is a relative address because it's the object
of a  JR NZ,CN9C  instruction.

   The offset is always the difference between the final location
(destination) and the local location (source).	Since the  $  operand
is by definition the local location,  $+OU  expands to:
$+OU   =   ($) + (OU)
       =   (LOCAL_LOC) + (FINAL_LOC - LOCAL_LOC)
       =   FINAL_LOC

   Hope this helps.    R.Gaspari.
